home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
gnu
/
nethack.lha
/
nethack-3.1
/
src
/
hacklib.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-18
|
12KB
|
509 lines
/* SCCS Id: @(#)hacklib.c 3.1 91/11/25 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* Copyright (c) Robert Patrick Rankin, 1991 */
/* NetHack may be freely redistributed. See license for details. */
/* We could only include config.h, except for the overlay definitions... */
#include "hack.h"
/*=
Assorted 'small' utility routines. They're virtually independent of
NetHack, except that rounddiv may call panic().
return type routine name argument type(s)
boolean digit (char)
boolean letter (char)
char highc (char)
char lowc (char)
char * lcase (char *)
char * eos (char *)
char * s_suffix (const char *)
char * xcrypt (const char *)
boolean onlyspace (const char *)
char * tabexpand (char *)
char * visctrl (char)
const char * ordin (int)
char * sitoa (int)
int sgn (int)
int rounddiv (long, int)
int distmin (int, int, int, int)
int dist2 (int, int, int, int)
boolean online2 (int, int)
boolean pmatch (const char *, const char *)
int strncmpi (const char *, const char *, int)
char * strstri (const char *, const char *)
void setrandom (void)
int getyear (void)
char * get_date (void)
int phase_of_the_moon (void)
boolean friday_13th (void)
int night (void)
int midnight (void)
=*/
#ifdef LINT
# define Static /* pacify lint */
#else
# define Static static
#endif
#ifdef OVLB
boolean
digit(c) /* is 'c' a digit? */
char c;
{
return '0' <= c && c <= '9';
}
boolean
letter(c) /* is 'c' a letter? note: '@' classed as letter */
char c;
{
return ('@' <= c && c <= 'Z') || ('a' <= c && c <= 'z');
}
#endif /* OVLB */
#ifdef OVL1
char
highc(c) /* force 'c' into uppercase */
char c;
{
return ('a' <= c && c <= 'z') ? (c & ~040) : c;
}
char
lowc(c) /* force 'c' into lowercase */
char c;
{
return ('A' <= c && c <= 'Z') ? (c | 040) : c;
}
#endif /* OVL1 */
#ifdef OVLB
char *
lcase(s) /* convert a string into all lowercase */
char *s;
{
register char *p;
for (p = s; *p; p++)
if ('A' <= *p && *p <= 'Z') *p |= 040;
return s;
}
#endif /* OVLB */
#ifdef OVL0
char *
eos(s) /* return the end of a string (pointing at '\0') */
register char *s;
{
while (*s) s++; /* s += strlen(s); */
return s;
}
char *
s_suffix(s) /* return a name converted to possessive */
const char *s;
{
Static char buf[BUFSZ];
Strcpy(buf, s);
if(!strcmpi(buf, "it"))
Strcat(buf, "s");
else if(*(eos(buf)-1) == 's')
Strcat(buf, "'");
else
Strcat(buf, "'s");
return buf;
}
char *
xcrypt(str) /* trivial text encryption routine (see makedefs) */
const char *str;
{
Static char buf[BUFSZ];
register const char *p;
register char *q;
register int bitmask;
for (bitmask = 1, p = str, q = buf; *p; q++) {
*q = *p++;
if (*q & (32|64)) *q ^= bitmask;
if ((bitmask <<= 1) >= 32) bitmask = 1;
}
*q = '\0';
return buf;
}
#endif /* OVL0 */
#ifdef OVL2
boolean
onlyspace(s) /* is a string entirely whitespace? */
const char *s;
{
for (; *s; s++)
if (*s != ' ' && *s != '\t') return FALSE;
return TRUE;
}
#endif /* OVL2 */
#ifdef OVLB
char *
tabexpand(sbuf) /* expand tabs into proper number of spaces */
char *sbuf;
{
char buf[BUFSZ];
register char *bp, *s = sbuf;
register int idx;
if (!*s) return sbuf;
/* warning: no bounds checking performed */
for (bp = buf, idx = 0; *s; s++)
if (*s == '\t') {
do *bp++ = ' '; while (++idx % 8);
} else {
*bp++ = *s;
idx++;
}
*bp = 0;
return strcpy(sbuf, buf);
}
char *
visctrl(c) /* make a displayable string from a character */
char c;
{
Static char ccc[3];
c &= 0177;
ccc[2] = '\0';
if (c < 040) {
ccc[0] = '^';
ccc[1] = c | 0100; /* letter */
} else if (c == 0177) {
ccc[0] = '^';
ccc[1] = c & ~0100; /* '?' */
} else {
ccc[0] = c; /* printable character */
ccc[1] = '\0';
}
return ccc;
}
#endif /* OVLB */
#ifdef OVL2
const char *
ordin(n) /* return the ordinal suffix of a number */
int n; /* note: should be non-negative */
{
register int dd = n % 10;
return (dd == 0 || dd > 3 || (n % 100) / 10 == 1) ? "th" :
(dd == 1) ? "st" : (dd == 2) ? "nd" : "rd";
}
#endif /* OVL2 */
#ifdef OVL1
char *
sitoa(n) /* make a signed digit string from a number */
int n;
{
Static char buf[13];
(void) sprintf(buf, (n < 0) ? "%d" : "+%d", n);
return buf;
}
int
sgn(n) /* return the sign of a number: -1, 0, or 1 */
int n;
{
return (n < 0) ? -1 : (n != 0);
}
#endif /* OVL1 */
#ifdef OVLB
int
rounddiv(x, y) /* calculate x/y, rounding as appropriate */
long x;
int y;
{
int r, m;
int divsgn = 1;
if (y == 0)
panic("division by zero in rounddiv");
else if (y < 0) {
divsgn = -divsgn; y = -y;
}
if (x < 0) {
divsgn = -divsgn; x = -x;
}
r = x / y;
m = x % y;
if (2*m >= y) r++;
return divsgn * r;
}
#endif /* OVLB */
#ifdef OVL0
int
distmin(x0, y0, x1, y1) /* distance between two points, in moves */
int x0, y0, x1, y1;
{
register int dx = x0 - x1, dy = y0 - y1;
if (dx < 0) dx = -dx;
if (dy < 0) dy = -dy;
/* The minimum number of moves to get from (x0,y0) to (x1,y1) is the
: larger of the [absolute value of the] two deltas.
*/
return (dx < dy) ? dy : dx;
}
int
dist2(x0, y0, x1, y1) /* square of euclidean distance between pair of pts */
int x0, y0, x1, y1;
{
register int dx = x0 - x1, dy = y0 - y1;
return dx * dx + dy * dy;
}
boolean
online2(x0, y0, x1, y1) /* are two points lined up (on a straight line)? */
int x0, y0, x1, y1;
{
register dx = x0 - x1, dy = y0 - y1;
/* If either delta is zero then they're on an orthogonal line,
: else if the deltas are equal (signs ignored) they're on a diagonal.
*/
return !dy || !dx || (dy == dx) || (dy + dx == 0); /* (dy == -dx) */
}
#endif /* OVL0 */
#ifdef OVLB
boolean
pmatch(patrn, strng) /* match a string against a pattern */
const char *patrn, *strng;
{
char s, p;
/*
: Simple pattern matcher: '*' matches 0 or more characters, '?' matches
: any single character. Returns TRUE if 'strng' matches 'patrn'.
*/
pmatch_top:
s = *strng++; p = *patrn++; /* get next chars and pre-advance */
if (!p) /* end of pattern */
return (s == '\0'); /* matches iff end of string too */
else if (p == '*') /* wildcard reached */
return (!*patrn || pmatch(patrn, strng-1)) ? TRUE :
s ? pmatch(patrn-1, strng) : FALSE;
else if (p != s && (p != '?' || !s)) /* check single character */
return FALSE; /* doesn't match */
else /* return pmatch(patrn, strng); */
goto pmatch_top; /* optimize tail recursion */
}
#endif /* OVLB */
#ifdef OVL2
#ifndef STRNCMPI
int
strncmpi(s1, s2, n) /* case insensitive counted string comparison */
register const char *s1, *s2;
register int n; /*(should probably be size_t, which is usually unsigned)*/
{ /*{ aka strncasecmp }*/
register char t1, t2;
while (n--) {
if (!*s2) return (*s1 != 0); /* s1 >= s2 */
else if (!*s1) return -1; /* s1 < s2 */
t1 = lowc(*s1++);
t2 = lowc(*s2++);
if (t1 != t2) return (t1 > t2) ? 1 : -1;
}
return 0; /* s1 == s2 */
}
#endif /* STRNCMPI */
#endif /* OVL2 */
#ifdef OVLB
#ifndef STRSTRI
/* A note on the #ifndef GCC_WARN: "const" unfortunately has two different
* meanings. One meaning for "const char *str" is that the data pointed
* to by "str" happens not to be modified by this function. That is true
* for strstri. Another meaning is that "str" is (or may be) a pointer
* to a constant string that must never be modified. gcc takes the latter
* interpretation, and warns us about possible subversion of the const
* modifier. Actually, that warning can be useful (we could accidentally
* turn a constant string into a non-constant one with this function)
* and so we note the fact that we're returning "str" as a non-const
* by declaring it as non-const if GCC_WARN is defined.
*/
char *
strstri(str, sub) /* case insensitive substring search */
#ifndef GCC_WARN
const
#endif
char *str;
const char *sub;
{
register const char *s1, *s2;
register int i, k;
# define TABSIZ 0x20 /* 0x40 would be case-sensitive */
char tstr[TABSIZ], tsub[TABSIZ]; /* nibble count tables */
# if 0
assert( (TABSIZ & ~(TABSIZ-1)) == TABSIZ ); /* must be exact power of 2 */
assert( &lowc != 0 ); /* can't be unsafe macro */
# endif
/* special case: empty substring */
if (!*sub) return (char *) str;
/* do some useful work while determining relative lengths */
for (i = 0; i < TABSIZ; i++) tstr[i] = tsub[i] = 0; /* init */
for (k = 0, s1 = str; *s1; k++) tstr[*s1++ & (TABSIZ-1)]++;
for ( s2 = sub; *s2; --k) tsub[*s2++ & (TABSIZ-1)]++;
/* evaluate the info we've collected */
if (k < 0) return (char *) 0; /* sub longer than str, so can't match */
for (i = 0; i < TABSIZ; i++) /* does sub have more 'x's than str? */
if (tsub[i] > tstr[i]) return (char *) 0; /* match not possible */
/* now actually compare the substring repeatedly to parts of the string */
for (i = 0; i <= k; i++) {
s1 = &str[i];
s2 = sub;
while (lowc(*s1++) == lowc(*s2++))
if (!*s2) return (char *) &str[i]; /* full match */
}
return (char *) 0; /* not found */
}
#endif /* STRSTRI */
#endif /* OVLB */
#ifdef OVL2
/*
* Time routines
*
* The time is used for:
* - seed for rand()
* - year on tombstone and yymmdd in record file
* - phase of the moon (various monsters react to NEW_MOON or FULL_MOON)
* - night and midnight (the undead are dangerous at midnight)
* - determination of what files are "very old"
*/
#if defined(AMIGA) && !defined(AZTEC_C) && !defined(__SASC_60)
extern struct tm *FDECL(localtime,(time_t *));
#endif
static struct tm *NDECL(getlt);
void
setrandom()
{
/* the types are different enough here that sweeping the different
* routine names into one via #defines is even more confusing
*/
#ifdef RANDOM /* srandom() from sys/share/random.c */
srandom((unsigned int) time((time_t *)0));
#else
# if defined(BSD) || defined(ULTRIX) /* system srandom() */
# ifdef BSD
# if defined(SUNOS4)
(void)
# endif
srandom((int) time((long *)0));
# else
srandom((int) time((time_t *)0));
# endif
# else
# ifdef UNIX /* system srand48() */
srand48((long) time((time_t *)0));
# else /* poor quality system routine */
srand((int) time((time_t *)0));
# endif
# endif
#endif
}
static struct tm *
getlt()
{
time_t date;
#ifdef BSD
(void) time((long *)(&date));
#else
(void) time(&date);
#endif
#if (defined(ULTRIX) && !(defined(ULTRIX_PROTO) || defined(NHSTDC))) || defined(BSD)
return(localtime((long *)(&date)));
#else
return(localtime(&date));
#endif
}
int
getyear()
{
return(1900 + getlt()->tm_year);
}
char *
get_date()
{
Static char datestr[7];
register struct tm *lt = getlt();
Sprintf(datestr, "%2d%2d%2d",
lt->tm_year, lt->tm_mon + 1, lt->tm_mday);
if(datestr[2] == ' ') datestr[2] = '0';
if(datestr[4] == ' ') datestr[4] = '0';
return(datestr);
}
int
phase_of_the_moon() /* 0-7, with 0: new, 4: full */
/* moon period: 2551442 seconds == 29.53058 days */
/* 722578680: date when there was a new moon (Tue Nov 24 04:18 1992) */
/* *8/2551442: divide into 8 phases */
/* *8 +2551442/2 /2551442: let the division round to nearest instead of down */
{
#ifdef BSD
long now = time((long *)0);
#else
long now = time((time_t *)0);
#endif
return (int) (((((now - 722578680L) % 2551442L) * 8L) + 2551442L/2L)
/ 2551442L);
}
boolean
friday_13th()
{
register struct tm *lt = getlt();
return (lt->tm_wday == 5 /* friday */ && lt->tm_mday == 13);
}
int
night()
{
register int hour = getlt()->tm_hour;
return(hour < 6 || hour > 21);
}
int
midnight()
{
return(getlt()->tm_hour == 0);
}
#endif /* OVL2 */
/*hacklib.c*/